#include "RenzoPrecompiled.h"
#include "RenzoLog.h"

#include <stdarg.h>

namespace Renzo {

Log* Log::log = 0;
Log* Log::instance() {
	if (log == 0) {
		log = new Log;
	}
	return log;
}

Log::Log(void) :
	_log_file(0), _err_file(0), _stdout_file(0), tab(0)
{
	open();
}

Log::~Log(void)
{
	close();
}

void Log::open() {
	char* _log_file_dir = (char*) malloc(1024);
	memset(_log_file_dir, 0, 1024);
	
	//CFStringRef homeDir = (CFStringRef)NSHomeDirectory();	
	
	//NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	//NSString *documentsDirectory = [paths objectAtIndex:0]; // get the first document directory available
	//CFStringRef documentDir = (CFStringRef)documentsDirectory;
	/*
	#if TARGET_IPHONE_SIMULATOR
		sprintf(_log_file_dir, "/tmp/");
	#else
		CFStringRef tmpDir = (CFStringRef)NSTemporaryDirectory();
		CFStringGetCString(tmpDir, _log_file_dir, 1024, kCFStringEncodingASCII);
	#endif
	*/

	sprintf(_log_file_dir, ".");

	char _log_file_path[1024], _error_file_path[1024], _stdout_file_path[1024];
	sprintf(_log_file_path, "%s/%s\0", _log_file_dir, FILE_LOG);
	sprintf(_error_file_path, "%s/%s\0", _log_file_dir, FILE_STDERR);
	sprintf(_stdout_file_path, "%s/%s\0", _log_file_dir, FILE_STDOUT);
	//strncpy(_log_file_dir + strlen(_log_file_dir), _log_file_name, strlen(_log_file_name));
	
	// redirect all stderr to a separate file
	_err_file		= freopen(_error_file_path, "w+", stderr);
	_stdout_file	= freopen(_stdout_file_path, "w+", stdout);
	
	// open log file
	_log_file = fopen(_log_file_path, "w+");
	if (_log_file == 0)
		rzError(ERROR_FILE_OPEN, _log_file_path);
	
	free(_log_file_dir);
	
	//return LOG_OK;
}

void Log::close() {
	if (_log_file != 0)
		fclose(_log_file);
	_log_file = 0;
	
	if (_err_file != 0)
		fclose(_err_file);
	_err_file = 0;
	
	if (_stdout_file != 0)
		fclose(_stdout_file);
	_stdout_file = 0;
	//return LOG_OK;
}

void Log::_write(const char* fmt, va_list ap) {
	// print time
	time_t time_sec;
	time(&time_sec);
	struct tm* timeData = localtime(&time_sec);
	fprintf(_log_file, "%04d-%02d-%02d %02d:%02d:%02d: ", timeData->tm_year + 1900, timeData->tm_mon + 1, timeData->tm_mday, timeData->tm_hour, timeData->tm_min, timeData->tm_sec);
	
	// print tab
	for (int i = 0; i < tab; i++)
		fprintf(_log_file, "\t");
	
	// print content
	vfprintf(_log_file, fmt, ap); // use vfprintf to accept a list of arguments
	fprintf(_log_file, "\n");
}

void Log::write(const char* fmt, ...) {
	va_list ap;
	va_start(ap, fmt);
	_write(fmt, ap);
	va_end(ap);
	
	// flush can be slow
	//fflush(_log_file);
	//fflush(_err_file);
	
	//free(timeData);
	//return LOG_OK;
}

void Log::tabWrite(const char* fmt, ...) {	
	va_list ap;
	va_start(ap, fmt); 
	_write(fmt, ap);
	va_end(ap);
	++tab;
}

void Log::untabWrite(const char* fmt, ...) {	
	--tab;
	va_list ap;
	va_start(ap, fmt); 
	_write(fmt, ap);
	va_end(ap);	
}

void Log::write(const char* fmt, va_list args) {
	_write(fmt, args);
}

}

